package com.googlecode.dgwt.client.dojo;

import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;


/**
 * @author	Wellington Tadeu dos Santos
 * @since	DGWT v0.01
 */
public class URL extends RequestBuilder {
	
	
	public URL(String url) {
		super(GET, url);
	}
	
	
	public URL(Method httpMethod, String url) {
		super(httpMethod, url);
	}
	
	
	public Response fetch() throws RequestException {
		return fetch(null);
	}
	

	public Response fetch(String requestData) throws RequestException {	
		return doSend(requestData);
	}

	
	protected native Response doSend(String requestData) throws RequestException /*-{
		var syncCallback = @com.googlecode.dgwt.client.dojo.URL.SyncRequestCallback::new()();
		var request = this.@com.googlecode.dgwt.client.dojo.URL::doSend(Ljava/lang/String;Lcom/google/gwt/http/client/RequestCallback;Z)(requestData, syncCallback, false);
		var response = syncCallback.@com.googlecode.dgwt.client.dojo.URL.SyncRequestCallback::response;
		var exception = syncCallback.@com.googlecode.dgwt.client.dojo.URL.SyncRequestCallback::exception;
		if (exception){
			throw @com.google.gwt.http.client.RequestException::new(Ljava/lang/Throwable;)(exception);
		}
		if (!response){
			response = @com.google.gwt.http.client.Request::createResponse(Lcom/google/gwt/core/client/JavaScriptObject;)(request.@com.google.gwt.http.client.Request::xmlHttpRequest);
		}
		return response; 
	}-*/;

	
	protected native Request doSend(String requestData, RequestCallback callback, boolean async) throws RequestException /*-{
	
		var openError,
			xmlHttpRequest = @com.google.gwt.http.client.RequestBuilder::httpRequest;
			xmlHttpRequest = xmlHttpRequest.@com.google.gwt.user.client.impl.HTTPRequestImpl::createXmlHTTPRequest()();
		
		if (this.@com.google.gwt.http.client.RequestBuilder::user != null 
			&& this.@com.google.gwt.http.client.RequestBuilder::password != null) {
			openError = @com.google.gwt.http.client.XMLHTTPRequest::open(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)(
				xmlHttpRequest, 
				this.@com.google.gwt.http.client.RequestBuilder::httpMethod, 
				this.@com.google.gwt.http.client.RequestBuilder::url,
				async, 
				this.@com.google.gwt.http.client.RequestBuilder::user, 
				this.@com.google.gwt.http.client.RequestBuilder::password
			);
		} 
		else 
		if (this.@com.google.gwt.http.client.RequestBuilder::user != null) {
			openError = @com.google.gwt.http.client.XMLHTTPRequest::open(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)(
				xmlHttpRequest, 
				this.@com.google.gwt.http.client.RequestBuilder::httpMethod, 
				this.@com.google.gwt.http.client.RequestBuilder::url,
				async,
				this.@com.google.gwt.http.client.RequestBuilder::user
			);
		} else {
			openError = @com.google.gwt.http.client.XMLHTTPRequest::open(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Ljava/lang/String;Z)(
				xmlHttpRequest, 
				this.@com.google.gwt.http.client.RequestBuilder::httpMethod, 
				this.@com.google.gwt.http.client.RequestBuilder::url,
				async
			);
		}

		if (openError != null) {
			var requestPermissionException = @com.google.gwt.http.client.RequestPermissionException::new()(
					this.@com.google.gwt.http.client.RequestBuilder::url);
			requestPermissionException.@com.google.gwt.http.client.RequestPermissionException::initCause(Ljava/lang/Throwable;)(@com.google.gwt.http.client.RequestException::new(Ljava/lang/String;)(openError));
			throw requestPermissionException;
		}

		this.@com.google.gwt.http.client.RequestBuilder::setHeaders(Lcom/google/gwt/core/client/JavaScriptObject;)(xmlHttpRequest);

		var request = @com.google.gwt.http.client.Request::new(Lcom/google/gwt/core/client/JavaScriptObject;ILcom/google/gwt/http/client/RequestCallback;)(
			xmlHttpRequest, 
			this.@com.google.gwt.http.client.RequestBuilder::timeoutMillis, 
			callback
		);

		var sendError = @com.google.gwt.http.client.XMLHTTPRequest::send(Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/http/client/Request;Ljava/lang/String;Lcom/google/gwt/http/client/RequestCallback;)(
			xmlHttpRequest, 
			request,
			requestData, 
			callback
		);
		
		if (sendError != null) {
			throw @com.google.gwt.http.client.RequestException::new(Ljava/lang/String;)(sendError);
		} 

		return request;
	}-*/;
	

	protected static class SyncRequestCallback implements RequestCallback {
		
		protected Response response = null;
		protected Throwable exception = null;
		
		@Override
		public void onError(Request request, Throwable exception) {
			this.exception = exception;
		}

		@Override
		public void onResponseReceived(Request request, Response response) {
			this.response = response;
		}
		
	}
	
}
